<template>
  <n-space class="basic-table-new" vertical>
    <div class="header">
      <div class="header__left">
        <slot name="tools"></slot>
      </div>
      <n-space class="header__right">
        <n-button type="primary" @click="onRefresh">刷新</n-button>

        <n-dropdown
          :show="showDropdown"
          :options="dropdownOptions"
          @clickoutside="showDropdown = false"
        >
          <n-button type="info" @click="showDropdown = !showDropdown">
            列设置
          </n-button>
        </n-dropdown>
      </n-space>
    </div>
    <div class="body">
      <n-data-table
        v-bind="$attrs"
        :columns="displayColumns"
        :data="rows"
        :loading="loading"
        :pagination="pagination"
      />
    </div>
  </n-space>
</template>

<script>
import { h } from "vue";
import { NCheckbox } from "naive-ui";
// 引入 axios
import axios from "axios";
// 引入 request
import request from "@/utils/request";

export default {
  name: "basic-table-new",

  // 禁用透传attrs的继承
  inheritAttrs: false,

  props: {
    // 接口地址
    api: { type: String, required: true },
    // 接口请求方式
    apiMethod: { type: String, default: "GET" },
    // 接口参数
    apiParams: { type: Object, default: () => ({}) },
    // 当前接口是否为json-server提供的假接口
    mock: { type: Boolean, default: false },
  },

  data() {
    return {
      // 表格行数据
      rows: [],
      // 数据总条数
      total: 1,
      // 加载中
      loading: false,

      // 控制列设置面板是否展示
      showDropdown: false,

      // 控制勾选框是否勾选
      isChecked: true,
      // 用于表示需要勾选的 column 的 key 名
      showColumnKeys: this.$attrs.columns.map((column) => column.key),
    };
  },

  computed: {
    dropdownOptions() {
      return this.$attrs.columns.map((column) => {
        // 当前这列是否勾选
        const isChecked = this.showColumnKeys.includes(column.key);

        return {
          key: column.key,
          label: () =>
            h(
              NCheckbox,
              {
                checked: isChecked,
                onUpdateChecked: (checked) => {
                  // 判断当前 column.key 是否在 showColumnKeys 中，
                  // 在就删除掉
                  // 不在就加进去
                  if (isChecked) {
                    // 在
                    this.showColumnKeys = this.showColumnKeys.filter(
                      (key) => key !== column.key
                    );
                  } else {
                    // 不在
                    this.showColumnKeys.push(column.key);
                  }
                },
              },
              { default: () => column.title }
            ),
        };
      });
    },

    // 用于表格的显示的 columns, 依赖项 this.$attrs.columns 与 this.showColumnKeys
    displayColumns() {
      return this.$attrs.columns.filter((column) => {
        // 当前 column.key 是否在 showColumnsKeys 中
        //  在就显示
        //  不在就隐藏
        return this.showColumnKeys.includes(column.key);
      });
    },

    // 分页数据
    pagination() {
      // 判断是否需要分页
      if (this.$attrs.pagination) {
        return {
          ...this.$attrs.pagination,
          pageCount: Math.ceil(this.total / this.$attrs.pagination.pageSize),
        };
      } else {
        return false;
      }
    },
  },

  // 这里做watch是一种方式，
  // 另一种方式更好，让组件直接通过ref获取到当前组件的实例对象，调用fetchData即可。
  // watch: {
  //   apiParams: {
  //     handler() {
  //       this.fetchData();
  //     },
  //     deep: true,
  //   },
  // },

  mounted() {
    this.fetchData();
  },

  methods: {
    /**
     * 请求数据
     */
    async fetchData() {
      try {
        this.loading = true;

        if (this.mock) {
          const { data } = await axios({
            url: this.api,
            method: "GET",
          });
          this.rows = data;
        } else {
          const options = {
            // 如果url地址是一个完整的请求地址，则不会拼接 baseURL
            url: this.api,
            method: this.apiMethod,
          };

          // params 配置项，是 ? 号传参
          // data 配置项，是 请求体 传参
          if (this.apiMethod === "GET") {
            options.params = this.apiParams;
          }

          if (this.apiMethod === "POST") {
            options.data = this.apiParams;
          }
          const response = await request(options);
          this.rows = response.data;
          this.total = response.total;
        }
      } finally {
        this.loading = false;
      }
    },

    /**
     * 刷新
     */
    onRefresh() {
      this.fetchData();
    },
  },
};
</script>

<style lang="scss" scoped>
.basic-table-new {
  padding: 8px 16px;
  background-color: #fff;
  .header {
    display: flex;
    justify-content: space-between;
  }
}
</style>
